<template>
  <div class="box">
    <div>
      <h2 class="left-align">Web SDK Video Quickstart</h2>
      <div class="row">
        <div>
          <!-- 主播和观众进入直播按钮 -->
          <button type="button" id="host-join" @click="hostJoinFn">主播进入</button>
          <button type="button" id="audience-join" @click="audienceJoinFn">观众进入</button>
          <button type="button" id="leave" @click="leaveFn">离开直播</button>
        </div>
        <div class="video-container">
          <!-- 本地用户视频容器 -->
          <div
            v-if="localPlayerContainer.role !== 'audience'"
            :id="localPlayerContainer.containerId"
            class="local-user"
          >
            {{ localPlayerContainer.text }}
            <!-- 视频元素 -->
            <div :id="localPlayerContainer.videoId" class="video-element"></div>
            <el-button color="#626aef" @click="shareFn">共享屏幕</el-button>
          </div>

          <!-- 动态生成的远程用户视频容器 -->
          <div
            v-for="user in remoteUsers"
            :key="user.uid"
            :id="user.containerId"
            class="remote-user"
          >
            {{ user.text }}
            <!-- 视频元素 -->
            <div :id="user.videoId" class="video-element"></div>
            <el-button color="#626aef" @click="shareFn">共享屏幕</el-button>
          </div>
        </div>
      </div>
    </div>
    <!-- 群聊区域 -->
    <div>
      <h2 class="left-align">Easemob Chat Examples</h2>
      <form @submit.prevent="handleSubmit">
        <div class="col" style="min-width: 433px; max-width: 443px">
          <div class="card" style="margin-top: 0px; margin-bottom: 0px">
            <div class="row card-content" style="margin-bottom: 0px; margin-top: 10px">
              <div class="input-field">
                <label>用户名</label>
                <input type="text" placeholder="Username" v-model="userID" />
              </div>
              <div class="input-field">
                <label>密码</label>
                <input type="password" placeholder="Password" v-model="password" />
              </div>
              <div class="row">
                <div>
                  <button type="button" @click="register">注册</button>
                  <button type="button" @click="login">登录</button>
                  <button type="button" @click="logout">登出</button>
                  <button type="button" @click="createLiveRoom">创建直播间</button>
                </div>
              </div>
              <div class="input-field">
                <label>接收消息：用户名</label>
                <input type="text" placeholder="Peer username" v-model="peerId" />
              </div>
              <div class="input-field">
                <label>消息</label>
                <input type="text" placeholder="Peer message" v-model="peerMessage" />
                <button type="button" @click="sendPeerMessage">发送消息</button>
              </div>
            </div>
          </div>
        </div>
      </form>
      <hr />
      <div id="log">
        <div v-for="logItem in log" :key="logItem">{{ logItem }}</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import WebIM from 'easemob-websdk'
import { ref, nextTick } from 'vue'
import AgoraRTC from 'agora-rtc-sdk-ng'
// 初始化 rtc 对象
const rtc = {
  localAudioTrack: null, // 本地麦克风音频轨道
  localVideoTrack: null, // 本地摄像头视频轨道
  client: AgoraRTC.createClient({ mode: 'live', codec: 'vp8' }) // Agora 客户端
}

// 初始化和 options 对象
const options = {
  appId: '4d2c2086196241d38337bb5145e781d6', // App ID
  channel: 'test', // 频道名称
  token:
    '007eJxTYJgQ8lg6oOGUytSjfiozDqSV8t3OOvlWx9wiKPP2olMn9cQVGExSjJKNDCzMDC3NjEwMU4wtjI3Nk5JMDU1MU80tDFPMnFz70xoCGRk0BLwZGKEQxGdhKEktLmFgAADgfhzR' // 认证 Token
}

const localPlayerContainer = ref({
  uid: 123456,
  text: `Local user 123456`,
  containerId: `local-container-123456`,
  videoId: `local-video-123456`,
  role: null
})

// 存储远程用户信息的数组
const remoteUsers = ref([])

// 当用户在频道中发布媒体轨道时触发
rtc.client.on('user-published', async (user, mediaType) => {
  await rtc.client.subscribe(user, mediaType)

  if (mediaType === 'video') {
    // 处理远程视频轨道
    const remoteVideoTrack = user.videoTrack
    const remotePlayerContainer = {
      uid: user.uid.toString(),
      text: 'Remote user ' + user.uid.toString(),
      containerId: `remote-container-${user.uid}`,
      videoId: `remote-video-${user.uid}`
    }
    remoteUsers.value.push(remotePlayerContainer)
    // 在 DOM 更新后播放远程视频
    await nextTick()
    remoteVideoTrack.play(remotePlayerContainer.videoId)
  }

  if (mediaType === 'audio') {
    // 处理远程音频轨道
    const remoteAudioTrack = user.audioTrack
    remoteAudioTrack.play()
  }
})

// 当用户在频道中取消发布媒体轨道时触发
rtc.client.on('user-unpublished', async (user, mediaType) => {
  await rtc.client.unsubscribe(user, mediaType)
  remoteUsers.value = remoteUsers.value.filter(remoteUser => remoteUser.uid !== user.uid.toString())
})

// 远端用户离线回调
rtc.client.on('user-left', user => {
  remoteUsers.value = remoteUsers.value.filter(remoteUser => remoteUser.uid !== user.uid.toString())
})

// 主播进入直播间
const hostJoinFn = async () => {
  const role = localPlayerContainer.value.role

  if (role === 'host') return

  await rtc.client.setClientRole('host')

  // 首次加入频道
  if (role === null) {
    // 主播加入频道并设置角色
    await rtc.client.join(options.appId, options.channel, options.token)
  }

  // 创建音频和视频轨道
  rtc.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack()
  rtc.localVideoTrack = await AgoraRTC.createCameraVideoTrack()

  // 发布本地音频和视频轨道
  await rtc.client.publish([rtc.localAudioTrack, rtc.localVideoTrack])

  // 创建本地视频播放器容器
  const uid = rtc.client.uid
  localPlayerContainer.value = {
    uid,
    text: `Local user ${uid}`,
    containerId: `local-container-${uid}`,
    videoId: `local-video-${uid}`,
    role: 'host'
  }

  // 在 DOM 更新后播放本地视频
  await nextTick()
  rtc.localVideoTrack.play(localPlayerContainer.value.videoId)
}

// 观众进入直播间
const audienceJoinFn = async () => {
  const role = localPlayerContainer.value.role

  if (role === 'audience') return

  if (role === 'host') {
    await rtc.client.unpublish([rtc.localAudioTrack, rtc.localVideoTrack])
  }

  // audience设置成观众
  await rtc.client.setClientRole('audience')
  localPlayerContainer.value.role = 'audience'

  // 首次加入频道
  if (role === null) {
    // 观众加入频道
    localPlayerContainer.value.uid = await rtc.client.join(
      options.appId,
      options.channel,
      options.token
    )
  }
}

// 共享屏幕
const shareFn = async () => {
  if (rtc.localScreenTrack) {
    // 如果已经在共享屏幕，则停止共享并恢复摄像头视频
    await rtc.client.unpublish(rtc.localScreenTrack)
    rtc.localScreenTrack.close()
    rtc.localScreenTrack = null

    await rtc.client.publish(rtc.localVideoTrack)
    rtc.localVideoTrack.play(localPlayerContainer.value.videoId)
  } else {
    // 停止摄像头视频
    await rtc.client.unpublish(rtc.localVideoTrack)
    rtc.localVideoTrack.stop()

    // 创建屏幕视频轨道和麦克风音频轨道
    const screenTracks = await AgoraRTC.createScreenVideoTrack(
      {
        encoderConfig: '720p',
        optimizationMode: 'motion' // "motion"流畅优先 "detail"清晰优先。
      },
      'auto' // 捕获计算机音频
    )

    if (Array.isArray(screenTracks)) {
      // 如果返回的是数组，表示包含视频轨道和音频轨道
      rtc.localScreenTrack = screenTracks[0]
      rtc.localAudioTrack = screenTracks[1]
      // 发布屏幕视频轨道和音频轨道
      await rtc.client.publish([rtc.localScreenTrack, rtc.localAudioTrack])
    } else {
      // 如果返回的不是数组，表示只包含视频轨道
      rtc.localScreenTrack = screenTracks
      // 发布屏幕视频轨道
      await rtc.client.publish([rtc.localScreenTrack])
    }

    // 播放屏幕视频
    rtc.localScreenTrack.play(localPlayerContainer.value.videoId)
  }
}

// 离开直播间
const leaveFn = async () => {
  // 关闭共享
  if (rtc.localScreenTrack) {
    await rtc.client.unpublish(rtc.localScreenTrack)
    rtc.localScreenTrack && rtc.localScreenTrack.close()
    rtc.localScreenTrack = null
  }
  // 关闭本地音频和视频轨道
  rtc.localAudioTrack && rtc.localAudioTrack.close()
  rtc.localVideoTrack && rtc.localVideoTrack.close()
  // 移除所有远程用户的视频容器
  rtc.client.remoteUsers.forEach(async user => {
    const playerContainer = document.getElementById(`remote-container-${user.uid}`)
    playerContainer && playerContainer.remove()
  })

  // 清空远程用户列表
  remoteUsers.value = []

  // 离开频道
  await rtc.client.leave()
  // 初始化用户角色状态
  localPlayerContainer.value.role = null
}

// -----------------------------聊天代码

const appKey = '1130240704154455#chatdemo'

const userID = ref('') // 用户名
const password = ref('') // 用户密码
const peerId = ref('') // 群聊id
const peerMessage = ref('') // 消息内容
const log = ref([]) // 消息列表
// 初始化
const conn = new WebIM.connection({
  appKey: appKey
})
// SDK 中的事件处理程序
conn.addEventHandler('connection&message', {
  // 监听用户登录成功后连接服务器成功
  onConnected: () => {
    log.value.push('连接成功')
  },
  // 监听用户注销
  onDisconnected: () => {
    log.value.push('注销成功')
  },
  // 在接收到文本消息时触发
  onTextMessage: message => {
    console.log(message)
    log.value.push(`远程用户: ${message.from} Message: ${message.msg}`)
  },
  // 在接收到文本消息发生错误时触发
  onError: error => {
    console.log('on error', error)
  }
})

// 注册
const register = () => {
  conn
    .registerUser({ username: userID.value, password: password.value })
    .then(() => {
      log.value.push(`Register user ${userID.value} success`)
    })
    .catch(() => {
      log.value.push(`${userID.value} already exists`)
    })
}

// 登录
const login = () => {
  conn
    .open({ user: userID.value, pwd: password.value })
    .then(() => {
      log.value.push('登录成功')
    })
    .catch(() => {
      log.value.push('登录失败')
    })
}

// 登出
const logout = () => {
  conn.close()
}

// 发送消息
const sendPeerMessage = () => {
  const option = {
    type: 'txt', // 消息类型。
    chatType: 'groupChat', // 会话类型：单聊、群聊和聊天室分别为 `singleChat`、`groupChat` 和 `chatRoom`，默认为单聊。
    to: peerId.value, // 消息接收方：单聊为对方用户 ID，群聊和聊天室分别为群组 ID 和聊天室 ID。
    msg: peerMessage.value // 消息内容。
  }
  const msg = WebIM.message.create(option)
  conn
    .send(msg)
    .then(() => {
      log.value.push(`Message send to: ${peerId.value} Message: ${peerMessage.value}`)
    })
    .catch(() => {
      console.log('send private text fail')
    })
}

// 创建直播间
const createLiveRoom = () => {
  const option = {
    data: {
      groupname: '卢伟公司群', // 群组名称
      desc: '卢总PUA群组', // 群组描述
      members: ['hzj'], // 成员的用户 ID 组成的数组，不包含群主的用户 ID
      public: true, // 是否为公开群
      approval: false, // 入群申请是否需群主或管理员审批
      allowinvites: false, // 是否允许普通群成员邀请人入群
      inviteNeedConfirm: false // 邀请加群时是否需要受邀用户确认
    }
  }
  // 创建直播间
  conn
    .createGroup(option)
    .then(res => {
      peerId.value = res.data.groupid // 赋值群聊id
      log.value.push(`群聊创建成功: ${res.data.groupid}`)
    })
    .catch(error => {
      log.value.push('群聊创建失败')
      console.error(error)
    })
}
</script>

<style scoped>
.box {
  display: flex;
}
.video-container {
  display: flex;
  flex-wrap: wrap;
}

.local-user,
.remote-user {
  width: 400px;
  height: 400px;
  margin: 10px;
  position: relative;
}

.video-element {
  width: 100%;
  height: 100%;
  background: black;
}
</style>
